package net.eyra.utiles;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class Periodo_old {

    /**
     * Formato aaaa-MM-dd HH:mm:ss
     */
    public final static int FECHA_INICIAL = 1;
    /**
     * Formato aaaa-MM-dd HH:mm:ss
     */
    public final static int FECHA_FINAL = 2;
    /**
     * Formato aaaa-MM-dd HH:mm:ss
     */
    public final static int FORMATO_FECHA_AAAA_MM_DD_HH_MM = 3;
    /**
     * Formato dd-MM-aaaa HH:mm:ss
     */
    public final static int FORMATO_FECHA_DD_MM_AAAA_HH_MM = 4;
    /**
     * Formato aaaa-MM-dd
     */
    public final static int FORMATO_FECHA_AAAA_MM_DD = 5;
    /**
     * Formato dd-MM-aaaa
     */
    public final static int FORMATO_FECHA_DD_MM_AAAA = 6;

    public final static int DIA = 5;
    public final static int MES = 6;
    public final static int ANNO = 7;
    public final static int HORA = 8;
    public final static int MINUTO = 9;

    public final static int ENERO = 0;
    public final static int FEBRERO = 1;
    public final static int MARZO = 2;
    public final static int ABRIL = 3;
    public final static int MAYO = 4;
    public final static int JUNIO = 5;
    public final static int JULIO = 6;
    public final static int AGOSTO = 7;
    public final static int SEPTIEMBRE = 8;
    public final static int OCTUBRE = 9;
    public final static int NOVIEMBRE = 10;
    public final static int DICIEMBRE = 11;

    private final GregorianCalendar fecha_inicial = (GregorianCalendar) GregorianCalendar.getInstance(new Locale("es", "ES"));
    private final GregorianCalendar fecha_final = (GregorianCalendar) GregorianCalendar.getInstance(new Locale("es", "ES"));
    private final static SimpleDateFormat sdf = new SimpleDateFormat();

    public static Date ConvertirAFecha(String fecha, int formato) throws ParseException {
        CambiarFormato(formato);
        return sdf.parse(fecha);
    }

    // /**
    // * Desde el inicio del año actual hasta la fecha indicada
    // *
    // * @param dia
    // * @param mes
    // * @param año
    // * @return
    // */
    // public static Periodo DesdePrimeroAñoHastaFecha(int dia, int mes, int año) {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.YEAR, año);
    // l_calendar.set(Calendar.MONTH, mes);
    // l_calendar.set(Calendar.DAY_OF_MONTH, dia);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.YEAR, año);
    // l_calendar.set(Calendar.MONTH, 0);
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }
    //
    // /**
    // * Desde el inicio del año actual hasta la fecha final del periodo
    // *
    // * @param periodo
    // * @return
    // */
    // public static Periodo DesdePrimeroAñoHastaFecha(Periodo periodo) {
    // return Periodo.DesdePrimeroAñoHastaFecha(periodo.getDato(Periodo.FECHA_FINAL, Periodo.DIA),
    // periodo.getDato(Periodo.FECHA_FINAL, Periodo.MES),
    // periodo.getDato(Periodo.FECHA_FINAL, Periodo.ANNO));
    // }
    //
    // /**
    // * Desde primero de año hasta hoy
    // *
    // * @return
    // */
    // public static Periodo DesdePrimeroAñoHastaHoy() {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.MONTH, 0);
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }
    //
    // /**
    // * @param dia
    // * No incluído. Sólo hasta las 00:00 de ese día
    // * @return
    // */
    // public static Periodo DesdePrimeroMesHastaDia(int dia) {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.DAY_OF_MONTH, dia);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }
    //
    // public static Periodo DesdePrimeroMesHastaHoy() {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }
    //
    // /**
    // * Sólo comprueba la fecha no la hora
    // *
    // * @param fecha
    // * @param formato
    // * @return
    // */
    // public static boolean esFechaCorrecta(String fecha, int formato) {
    // CambiarFormato(formato);
    // try {
    // Calendar c = Calendar.getInstance();
    // c.setTimeInMillis(sdf.parse(fecha).getTime());
    // return true;
    // } catch (ParseException e) {
    // return false;
    // }
    // }
    //
    // public static Periodo PeriodoMes(int mes) {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.MONTH, mes);
    // l_calendar.set(Calendar.DAY_OF_MONTH, l_calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.MONTH, mes);
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }
    //
    // /**
    // * @param dia
    // * No incluído. Sólo hasta las 00:00 de ese día
    // * @return
    // */
    // public static Periodo PeriodoMesHastaDia(int dia, int mes) {
    // Calendar l_calendar = Calendar.getInstance();
    // Date l_fecha_final = new Date();
    // Date l_fecha_inicial = new Date();
    //
    // l_calendar.set(Calendar.MONTH, mes);
    // l_calendar.set(Calendar.DAY_OF_MONTH, dia);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 0);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_final.setTime(l_calendar.getTimeInMillis());
    //
    // l_calendar.set(Calendar.MONTH, mes);
    // l_calendar.set(Calendar.DAY_OF_MONTH, 1);
    // l_calendar.set(Calendar.HOUR_OF_DAY, 1);
    // l_calendar.set(Calendar.MINUTE, 0);
    // l_calendar.set(Calendar.SECOND, 0);
    // l_calendar.set(Calendar.MILLISECOND, 0);
    // l_fecha_inicial.setTime(l_calendar.getTimeInMillis());
    //
    // return new Periodo(l_fecha_inicial, l_fecha_final);
    // }

    private static void CambiarFormato(int formato) {
        if (formato == 3) sdf.applyLocalizedPattern("yyyy-MM-dd HH:mm:ss");
        if (formato == 4) sdf.applyLocalizedPattern("dd-MM-yyyy HH:mm:ss");
        if (formato == 5) sdf.applyLocalizedPattern("yyyy-MM-dd");
        if (formato == 6) sdf.applyLocalizedPattern("dd-MM-yyyy");
    }

    /**
     * Desde el inicio del año actual hasta la fecha indicada
     * 
     * @param dia
     * @param mes
     * @param año
     * @return
     */
    public void DesdePrimeroAñoHastaFecha(int dia, int mes, int año) {
        fecha_final.set(Calendar.YEAR, año);
        fecha_final.set(Calendar.MONTH, mes);
        fecha_final.set(Calendar.DAY_OF_MONTH, dia);
        fecha_final.set(Calendar.HOUR_OF_DAY, 0);
        fecha_final.set(Calendar.MINUTE, 0);
        fecha_final.set(Calendar.SECOND, 0);
        fecha_final.set(Calendar.MILLISECOND, 0);

        fecha_inicial.set(Calendar.YEAR, año);
        fecha_inicial.set(Calendar.MONTH, 0);
        fecha_inicial.set(Calendar.DAY_OF_MONTH, 1);
        fecha_inicial.set(Calendar.HOUR_OF_DAY, 1);
        fecha_inicial.set(Calendar.MINUTE, 0);
        fecha_inicial.set(Calendar.SECOND, 0);
        fecha_inicial.set(Calendar.MILLISECOND, 0);
    }

    /**
     * Desde el inicio del año actual hasta la fecha final
     * 
     * @param dia
     * @param mes
     * @param año
     * @return
     */
    public void DesdePrimeroAñoHastaFecha() {
        fecha_final.set(Calendar.HOUR_OF_DAY, 0);
        fecha_final.set(Calendar.MINUTE, 0);
        fecha_final.set(Calendar.SECOND, 0);
        fecha_final.set(Calendar.MILLISECOND, 0);

        fecha_inicial.set(Calendar.YEAR, fecha_final.get((Calendar.YEAR)));
        fecha_inicial.set(Calendar.MONTH, 0);
        fecha_inicial.set(Calendar.DAY_OF_MONTH, 1);
        fecha_inicial.set(Calendar.HOUR_OF_DAY, 1);
        fecha_inicial.set(Calendar.MINUTE, 0);
        fecha_inicial.set(Calendar.SECOND, 0);
        fecha_inicial.set(Calendar.MILLISECOND, 0);
    }

    public Periodo_old() {
    }

    /**
     * Se considera fecha final la actual.
     * 
     * @param fecha_inicial
     */
    public Periodo_old(Date fecha_inicial) {
        setFecha_inicial(fecha_inicial);
        setFecha_final(FechaActual());
    }

    public Periodo_old(Date fecha_inicial, Date fecha_final) {
        setFecha_inicial(fecha_inicial);
        setFecha_final(fecha_final);
    }

    public Periodo_old(Periodo_old periodo) {
        setFecha_inicial(periodo.getFecha_inicial());
        setFecha_final(periodo.getFecha_final());
        fecha_final.set(Calendar.MONTH, 0);
    }

    public Periodo_old(String fecha_inicial, int formato) throws FormateoFechaException {
        CambiarFormato(formato);
        setFecha_inicial(ParsearFecha(fecha_inicial));
        setFecha_final(FechaActual());
    }

    public Periodo_old(String fecha_inicial, String fecha_final, int formato) throws FormateoFechaException {
        CambiarFormato(formato);
        setFecha_inicial(ParsearFecha(fecha_inicial));
        setFecha_final(ParsearFecha(fecha_final));
    }

    /**
     * Compara 2 fecha pero sin tener en cuenta la hora, los minutos y los segundos.
     * 
     * @return Si la fecha final es menor devuelve -1, si es mayor devuelve 1 y si son iguales 0;
     */
    public int CompararFechas() {
        Date tmp_inicial = (Date) this.getFecha_inicial().clone();
        Date tmp_final = (Date) this.getFecha_final().clone();
        Calendar calendar = Calendar.getInstance();

        calendar.setTime(tmp_inicial);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        tmp_inicial = calendar.getTime();

        calendar.setTime(tmp_final);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        tmp_final = calendar.getTime();

        int valor = tmp_inicial.compareTo(tmp_final);

        if (valor > 0) return -1;
        return (valor == 0 ? 0 : 1);
    }

    /**
     * Compara 2 fecha teniendo en cuenta la hora, los minutos y los segundos.
     * 
     * @return Si la fecha final es menor devuelve -1, si es mayor devuelve 1 y si son iguales 0;
     */
    public int CompararFechasCompletas() {
        Date tmp_inicial = (Date) this.getFecha_inicial().clone();
        Date tmp_final = (Date) this.getFecha_final().clone();

        int valor = tmp_inicial.compareTo(tmp_final);

        if (valor > 0) return -1;
        return (valor == 0 ? 0 : 1);
    }

    public void Decrementar(int fecha, int medida, int unidades) {
        Incrementar(fecha, medida, unidades * -1);
    }

    public long DiferenciaEnDias() {
        return (fecha_final.getTimeInMillis() - fecha_inicial.getTimeInMillis()) / (1000 * 60 * 60 * 24);
    }

    /**
     * @param fecha
     * @return Regresa 'true' si la fecha esta dentro del periodo. Incluye ambos limites del periodo.
     */
    public boolean estaFechaEnPeriodo(Date fecha) {
        if (getFecha_inicial().getTime() <= fecha.getTime() && getFecha_final().getTime() >= fecha.getTime()) return true;
        return false;
    }

    /**
     * Devuelve un dato solicitado (mes, dia, año, hora, minuto) de la fecha indicada.(utilizar constantes estáticas). Si se solicita algún dato
     * inexistente o no existe la fecha para el dato solicitado, se devuelve 0;
     * 
     * @param fecha
     * @param dato
     * @return
     */
    public int getDato(int fecha, int dato) {
        Calendar calendar = Calendar.getInstance();
        if (fecha == Periodo_old.FECHA_INICIAL) calendar.setTimeInMillis(this.fecha_inicial.getTimeInMillis());

        if (fecha == Periodo_old.FECHA_FINAL) calendar.setTimeInMillis(this.fecha_final.getTimeInMillis());

        switch (dato) {
            case Periodo_old.DIA:
                return calendar.get(Calendar.DAY_OF_MONTH);
            case Periodo_old.MES:
                return calendar.get(Calendar.MONTH);
            case Periodo_old.ANNO:
                return calendar.get(Calendar.YEAR);
            case Periodo_old.HORA:
                return calendar.get(Calendar.HOUR_OF_DAY);
            case Periodo_old.MINUTO:
                return calendar.get(Calendar.MINUTE);
        }

        return 0;
    }

    public int getDiasMes(int fecha) {
        if (Periodo_old.FECHA_INICIAL == fecha) return fecha_inicial.getActualMaximum(Calendar.DAY_OF_MONTH);
        if (Periodo_old.FECHA_FINAL == fecha) return fecha_final.getActualMaximum(Calendar.DAY_OF_MONTH);
        return 0;
    }

    public Date getFecha_final() {
        return fecha_final.getTime();
    }

    public Date getFecha_inicial() {
        return fecha_inicial.getTime();
    }

    /**
     * @param formato
     *            . Usar las constantes tipo 'FORMATO_FECHA_??????'
     * @param fecha
     *            . Usar las constantes FECHA_INICIAL ó FECHA_FINAL
     * @return
     * @throws FormateoFechaException
     */
    public Date getFechaFormateada(int fecha) throws FormateoFechaException {
        Date _fecha = new Date();

        if (Periodo_old.FECHA_INICIAL == fecha) _fecha = ParsearFecha(fecha_inicial.getTime());
        if (Periodo_old.FECHA_FINAL == fecha) _fecha = ParsearFecha(fecha_final.getTime());

        return _fecha;
    }

    /**
     * Se debe formatear primero la fecha con la funcion 'public Date getFechaFormateada(int formato, int fecha) throws FormateoFechaException'
     * 
     * @param fecha
     * @return
     */
    public String getFechaFormateada(int formato, int fecha) {
        CambiarFormato(formato);
        if (Periodo_old.FECHA_INICIAL == fecha) return sdf.format(getFecha_inicial());
        if (Periodo_old.FECHA_FINAL == fecha) return sdf.format(getFecha_final());
        return null;
    }

    public String getMesAñoActual() {
        sdf.applyLocalizedPattern("MM-yyyy");
        return sdf.format(getFecha_inicial());
    }

    public void Incrementar(int fecha, int medida, int unidades) {
        Calendar calendar = null;
        if (fecha == Periodo_old.FECHA_INICIAL) calendar = this.fecha_inicial;
        else calendar = this.fecha_final;

        switch (medida) {
            case Periodo_old.DIA:
                calendar.add(Calendar.DAY_OF_MONTH, unidades);
                break;
            case Periodo_old.MES:
                calendar.add(Calendar.MONTH, unidades);
                break;
            case Periodo_old.ANNO:
                calendar.add(Calendar.YEAR, unidades);
                break;
            case Periodo_old.HORA:
                calendar.add(Calendar.HOUR_OF_DAY, unidades);
                break;
            case Periodo_old.MINUTO:
                calendar.add(Calendar.MINUTE, unidades);
                break;
        }
        // if (fecha == Periodo.FECHA_INICIAL) setFecha_inicial(calendar.getTime());
        // if (fecha == Periodo.FECHA_FINAL) setFecha_final(calendar.getTime());
    }

    /**
     * Crea un periodo del mes de la 'fecha_mes', desde el día 1 a las 01:00 horas hasta el ultimo dia del mes a las 00:00 horas.
     * 
     * @param fecha_mes
     */
    public void PeriodoMes(Date fecha_mes) {
        this.setFecha_inicial(fecha_mes);
        this.fecha_inicial.set(Calendar.DAY_OF_MONTH, 1);
        this.fecha_inicial.set(Calendar.HOUR_OF_DAY, 1);
        this.fecha_inicial.set(Calendar.MINUTE, 0);

        this.setFecha_final(fecha_inicial.getTime());
        this.fecha_final.set(Calendar.DAY_OF_MONTH, 1);
        this.fecha_final.set(Calendar.HOUR_OF_DAY, 0);
        this.fecha_final.set(Calendar.MINUTE, 0);
        this.Incrementar(FECHA_FINAL, MES, 1);
    }

    public void PeriodoMes(int mes) {
        fecha_inicial.set(MES, mes);
        fecha_inicial.set(DIA, 1);
        fecha_inicial.set(HORA, 1);
        fecha_inicial.set(MINUTO, 0);

        this.fecha_final.set(MES, mes);
        this.fecha_final.set(DIA, 1);
        this.fecha_final.set(HORA, 0);
        this.fecha_final.set(MINUTO, 0);
        this.Incrementar(FECHA_FINAL, MES, 1);
    }

    public void setFecha_final(Date fecha_final) {
        this.fecha_final.setTime(fecha_final);
        this.fecha_final.set(Calendar.SECOND, 0);
        this.fecha_final.set(Calendar.MILLISECOND, 0);

    }

    public void setFecha_final(String fecha, int formato) throws FormateoFechaException {
        CambiarFormato(formato);
        setFecha_final(ParsearFecha(fecha));
    }

    public void setFecha_inicial(Date fecha_inicial) {
        this.fecha_inicial.set(Calendar.SECOND, 0);
        this.fecha_inicial.set(Calendar.MILLISECOND, 0);
        this.fecha_inicial.setTime(fecha_inicial);
    }

    public void setFecha_inicial(String fecha, int formato) throws FormateoFechaException {
        CambiarFormato(formato);
        setFecha_inicial(ParsearFecha(fecha));
    }

    public boolean SolapaPeriodo(Periodo_old periodo) {
        if (estaFechaEnPeriodo(periodo.getFecha_inicial())) return true;

        if (estaFechaEnPeriodo(periodo.getFecha_final())) return true;

        if (periodo.getFecha_inicial().getTime() <= getFecha_inicial().getTime() && periodo.getFecha_final().getTime() >= getFecha_final().getTime())
            return true;
        return false;
    }

    private Date FechaActual() {
        return new Date(System.currentTimeMillis());
    }

    private Date ParsearFecha(Date fecha) throws FormateoFechaException {
        try {
            return sdf.parse(sdf.format(fecha.getTime()));
        } catch (ParseException e) {
            throw new FormateoFechaException(fecha.toString());
        }
    }

    private Date ParsearFecha(String fecha) throws FormateoFechaException {
        try {
            return sdf.parse(fecha);
        } catch (ParseException e) {
            throw new FormateoFechaException(fecha.toString());
        }
    }
}
